package com.anivia.common.web.config.mybatisPlus;

import cn.hutool.core.convert.Convert;
import com.anivia.common.web.config.dataScope.MyDataPermissionHandler;
import com.anivia.common.web.config.dataScope.MyDataPermissionInterceptor;
import com.anivia.common.web.satoken.util.UserInfoUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.reflections.Reflections;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashSet;
import java.util.Set;

/**
 * MyBatisPlus 全局配置
 *
 * @author wangj
 */
@Slf4j
@RefreshScope
@Configuration
public class MyBatisPlusConfig {
    /**
     * 不需要自动拼接租户id的表
     */
    private static Set<String> ignoreTableSet = new HashSet<>();

    static {
        Reflections reflections = new Reflections("com.anivia");
        Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(TableName.class);
        for (Class<?> clazz : typesAnnotatedWith) {
            TableName annotation = clazz.getAnnotation(TableName.class);
            if (annotation.excludeProperty().length > 0) {
                ignoreTableSet.add(annotation.value());
            }
        }
    }

    /**
     * 自动填充功能
     *
     * @return global config
     */
    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setMetaObjectHandler(new MetaHandler());
        return globalConfig;
    }

    /**
     * 拦截器配置
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                if (UserInfoUtil.isLogin()) {
                    return new LongValue(Convert.toLong(UserInfoUtil.getTenantId()));
                } else {
                    return null;
                }
            }

            @Override
            public boolean ignoreTable(String tableName) {
                return ignoreTableSet.contains(tableName);
            }
        }));

        // 添加数据权限插件
        mybatisPlusInterceptor.addInnerInterceptor(new MyDataPermissionInterceptor(new MyDataPermissionHandler()));
        // 乐观锁插件
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 数据变更记录插件
        mybatisPlusInterceptor.addInnerInterceptor(new MyDataChangeRecorderInnerInterceptor());
        // 防止全表更新或删除
        mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        // Mysql分页
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}
